import { reqeustImage } from '@geovis3d/shared';
import type { Cartesian2 } from 'cesium';

/**
 * 嵌入图片
 */
export interface EmbedImage {
  /**
   * url|base64
   */
  image: string;

  /**
   * 宽
   * @defaultValue image.width 图片大小
   */
  width?: number;

  /**
   * 高
   * @defaultValue image.height 图片大小
   */
  height?: number;

  /**
   * 偏移
   * @defaultValue Cartesian2(0,0)
   */
  offset?: Cartesian2;
}

/**
 * 嵌入文字
 */
export interface EmbedText {
  /**
   * 文本内容
   */
  text: string;

  /**
   * 字体配置、大小
   */
  font?: string;

  /**
   * 字体颜色
   */
  color?: string;

  /**
   * 偏移
   * @defaultValue Cartesian2(0,0)
   */
  offset?: Cartesian2;
}

/**
 * 嵌入项
 */
export type EmbedItem = EmbedImage | EmbedText;

/**
 * EmbedImageMaterialProperty构造参数
 */
export interface EmbedImageOptions {
  background?: string;

  /**
   * @defaultValue background.width 底图大小 | 100
   */
  width?: number;

  /**
   * @defaultValue background.height 底图大小 | 100
   */
  height?: number;

  /**
   * 嵌入项
   */
  embeds?: EmbedItem[];
}

/**
 * 将配置中的选项绘制到同一个canvas中
 * @param options - 配置项
 * @returns
 */
export async function embedImage(options: EmbedImageOptions = {}): Promise<HTMLCanvasElement> {
  const { embeds = [] } = options;
  const getBackgroundImage = async () => {
    const url = options.background;
    return options.background ? await reqeustImage(url!) : undefined;
  };

  const embedImageOptionMap = new Map<number, EmbedImage>();
  embeds.forEach((item: any, index) => {
    if (item.image) {
      embedImageOptionMap.set(index, item as EmbedImage);
    }
  });

  const getEmbedImages = async () => {
    const res = new Map<number, HTMLImageElement>();
    const iamgePromises = Array.from(embedImageOptionMap.entries()).map(async ([index, embed]) =>
      res.set(index, await reqeustImage(embed.image)),
    );
    await Promise.all(iamgePromises);
    return res;
  };
  const embedImageMap = await getEmbedImages();
  const backgroundImage = await getBackgroundImage();

  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d')!;

  canvas.width = options.width ?? backgroundImage?.width ?? 100;
  canvas.height = options.height ?? backgroundImage?.height ?? 100;

  context.rect(0, 0, canvas.width, canvas.height);
  context.fillStyle = 'rgba(0, 0, 0, 0)';
  context.fillRect(30, 30, 55, 50);
  if (backgroundImage) {
    context.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
  }

  embeds.forEach((item: any, index) => {
    const { x = 0, y = 0 } = item.offset ?? {};
    if (item.image) {
      const image = embedImageMap.get(index);
      const width = item.width ?? image?.width;
      const height = item.height ?? image?.height;
      const left = canvas.width / 2 - width / 2 + x;
      const top = canvas.height / 2 - height / 2 + y;
      context.drawImage(image!, left, top, width, height);
    } else {
      const { font, text, color = '#fff' } = item as EmbedText;
      context.fillStyle = color;
      context.font = font || '';
      context.textAlign = 'center';
      context.textBaseline = 'middle';
      const left = canvas.width / 2 + x;
      const top = canvas.height / 2 + y;
      context.fillText(text || '', left, top);
    }
  });

  return canvas;
}
